﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YJKArchMethodLibrary.BreakWallByLevel;
using YJKRGeometry;
using StairsModuleAndEdit.HYElevator.Manage;
using StructureModelDeduction.Data;

namespace StructureModelDeduction.Kit
{
	public class IntersectionInformGetterForWall : IntersectionInformGetter
	{
		public List<ElementId> LstWallIdHasIntersectionComponet
		{
			get
			{
				return this.m_lstWallIdHasIntersectionComponet;
			}
			set
			{
				this.m_lstWallIdHasIntersectionComponet = value;
			}
		}

		public IntersectionInformGetterForWall(Document doc, ElementDataPack elemData) : base(doc, elemData, null)
		{
		}

		public override int CheckRelationType()
		{
			List<Curve> list = null;
			(base.ElementData as WallDataPack).GetZFaceLoop(out list);
			Transform linkDocTransForm = Transform.CreateTranslation(XYZ.Zero);
			int elementInterSecByLinkSolid = this.GetElementInterSecByLinkSolid();
			foreach (ElementId elementId in this.m_lstWallIdHasIntersectionComponet)
			{
				WallDataPack item = new WallDataPack(this.m_Doc, ElementId.InvalidElementId, elementId, linkDocTransForm);
				this.m_lstDisPlay.Add(item);
			}
			if (elementInterSecByLinkSolid == 0)
			{
				return 0;
			}
			(base.ElementData as WallDataPack).GetWallCrv();
			this.m_LinkWallCrv = (base.ElementData as WallDataPack).LocatinCrv;
			List<Curve> parallelCrv = this.GetParallelCrv(list);
			List<ElementId> list2 = new List<ElementId>();
			foreach (ElementId elementId2 in this.m_lstCurrentId)
			{
				WallDataPack currentDocElemData = new WallDataPack(this.m_Doc, ElementId.InvalidElementId, elementId2, linkDocTransForm);
				int count = this.m_lstDeduction.Count;
				this.CheckRalationTypeSingleCouple(parallelCrv, currentDocElemData);
				int count2 = this.m_lstDeduction.Count;
				if (count2 == count)
				{
					list2.Add(elementId2);
				}
			}
			if (list2.Count > 1)
			{
				this.CheckStructWallNotInOneArchWall(list, list2);
			}
			else
			{
				foreach (ElementId elementId3 in list2)
				{
					WallDataPack item2 = new WallDataPack(this.m_Doc, ElementId.InvalidElementId, elementId3, linkDocTransForm);
					base.lstDisplay.Add(item2);
				}
			}
			return 1;
		}

		private List<Curve> GetParallelCrv(List<Curve> lstRawCrv)
		{
			List<Curve> list = new List<Curve>();
			if (this.m_LinkWallCrv.IsCyclic)
			{
				using (List<Curve>.Enumerator enumerator = lstRawCrv.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						Curve curve = enumerator.Current;
						if (curve.IsCyclic)
						{
							list.Add(curve);
						}
					}
					return list;
				}
			}
			XYZ xyz = (this.m_LinkWallCrv as Line).Direction.Normalize();
			foreach (Curve curve2 in lstRawCrv)
			{
				if (!curve2.IsCyclic)
				{
					XYZ xyz2 = (curve2 as Line).Direction.Normalize();
					if (xyz2.IsAlmostEqualTo(xyz) || xyz2.IsAlmostEqualTo(xyz.Negate()))
					{
						list.Add(curve2);
					}
				}
			}
			return list;
		}

		public override void CheckRalationTypeSingleCouple(List<Curve> lstLinkDocElemCurve, ElementDataPack CurrentDocElemData)
		{
			List<Curve> lstRawCrv = null;
			(CurrentDocElemData as WallDataPack).GetZFaceLoop(out lstRawCrv);
			List<Curve> parallelCrv = this.GetParallelCrv(lstRawCrv);
			if (this.CheckIfConside(parallelCrv, lstLinkDocElemCurve) == 0)
			{
				this.m_lstDeduction.Add(CurrentDocElemData);
			}
		}

		public void CheckStructWallNotInOneArchWall(List<Curve> lstLinkDocElemCurve, List<ElementId> lstSecondCompare)
		{
			List<Curve> list = new List<Curve>();
			Transform linkDocTransForm = Transform.CreateTranslation(XYZ.Zero);
			List<WallDataPack> list2 = new List<WallDataPack>();
			foreach (ElementId elementId in lstSecondCompare)
			{
				WallDataPack wallDataPack = new WallDataPack(this.m_Doc, ElementId.InvalidElementId, elementId, linkDocTransForm);
				list2.Add(wallDataPack);
				List<Curve> lstRawCrv = new List<Curve>();
				wallDataPack.GetZFaceLoop(out lstRawCrv);
				list.AddRange(this.GetParallelCrv(lstRawCrv));
			}
			if (!this.CheckifEndToEnd(list))
			{
				this.m_lstDisPlay.AddRange(list2);
				return;
			}
			if (this.CheckIfConside(list, lstLinkDocElemCurve) == 0)
			{
				this.m_lstDeduction.AddRange(list2);
				return;
			}
			this.m_lstDisPlay.AddRange(list2);
		}

		private bool CheckifEndToEnd(List<Curve> lstCheckCrv)
		{
			double num = 0.0;
			foreach (Curve curve in lstCheckCrv)
			{
				num += curve.Length;
			}
			Curve curve2 = lstCheckCrv[0].Clone();
			(curve2 as Line).MakeUnbound();
			double num2 = double.MaxValue;
			double num3 = double.MinValue;
			for (int i = 0; i < lstCheckCrv.Count; i++)
			{
				Curve curve3 = lstCheckCrv[i];
				double parameter = curve2.Project(curve3.GetEndPoint(0)).Parameter;
				double parameter2 = curve2.Project(curve3.GetEndPoint(1)).Parameter;
				double num4 = (parameter > parameter2) ? parameter : parameter2;
				double num5 = (parameter < parameter2) ? parameter : parameter2;
				if (Geometry.GreaterThan(num5, num3))
				{
					num3 = num5;
				}
				if (Geometry.LessThan(num4, num2))
				{
					num2 = num4;
				}
			}
			XYZ xyz = curve2.Evaluate(num2, false);
			XYZ xyz2 = curve2.Evaluate(num3, false);
			double val = xyz.DistanceTo(xyz2);
			return Geometry.IsEqual(val, num);
		}

		private int CheckIfConside(List<Curve> lstCrvBase, List<Curve> lstCrvChecked)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (Curve curve in lstCrvChecked)
			{
				list.Add(curve.GetEndPoint(0));
				list.Add(curve.GetEndPoint(1));
				if (curve is Arc)
				{
					list.Add(curve.Evaluate(0.3, true));
					list.Add(curve.Evaluate(0.6, true));
					list.Add(curve.Evaluate(0.9, true));
				}
			}
			int result = 0;
			foreach (XYZ xyz in list)
			{
				XYZ xyz2 = new XYZ(xyz.X, xyz.Y, lstCrvBase[0].GetEndPoint(0).Z);
				double num = double.MaxValue;
				foreach (Curve curve2 in lstCrvBase)
				{
					double num2 = curve2.Distance(xyz2);
					if (Geometry.LessThan(num2, num))
					{
						num = num2;
					}
				}
				if (!Geometry.IsEqual(num, 0.0, 0.0001))
				{
					result = -1;
					break;
				}
			}
			return result;
		}

		public override int GetElementInterSecByLinkSolid()
		{
			XYZ xyz = new XYZ(base.ElementData.TransFormedBoundBox.Min.X, base.ElementData.TransFormedBoundBox.Min.Y, base.ElementData.TransFormedBoundBox.Min.Z + 0.1);
			XYZ xyz2 = new XYZ(base.ElementData.TransFormedBoundBox.Max.X, base.ElementData.TransFormedBoundBox.Max.Y, base.ElementData.TransFormedBoundBox.Max.Z - 0.1);
			Outline outline = new Outline(xyz, xyz2);
			BoundingBoxIntersectsFilter boundingBoxIntersectsFilter = new BoundingBoxIntersectsFilter(outline);
			ElementClassFilter elementClassFilter = new ElementClassFilter(typeof(Wall));
			LogicalAndFilter logicalAndFilter = new LogicalAndFilter(elementClassFilter, boundingBoxIntersectsFilter);
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc);
			filteredElementCollector.WherePasses(logicalAndFilter).WhereElementIsNotElementType().ToElementIds();
			WallDataPack wallDataPack = base.ElementData as WallDataPack;
			wallDataPack.GetWallCrv();
			Curve locatinCrv = wallDataPack.LocatinCrv;
			List<ElementId> elementBySolidAndClassify = this.GetElementBySolidAndClassify(filteredElementCollector, locatinCrv);
			if (elementBySolidAndClassify.Count == 0)
			{
				return elementBySolidAndClassify.Count;
			}
			List<ElementId> wallHasComponetIntersectionWithLinkWall = this.GetWallHasComponetIntersectionWithLinkWall();
			for (int i = elementBySolidAndClassify.Count<ElementId>() - 1; i >= 0; i--)
			{
				ElementId elemid = elementBySolidAndClassify.ElementAt(i);
				int num = wallHasComponetIntersectionWithLinkWall.FindIndex((ElementId e) => e.IntegerValue == elemid.IntegerValue);
				if (num == -1)
				{
					this.m_lstCurrentId.Add(elemid);
				}
				else
				{
					this.LstWallIdHasIntersectionComponet.Add(elemid);
				}
			}
			return this.m_lstCurrentId.Count;
		}

		public List<ElementId> GetElementBySolidAndClassify(FilteredElementCollector Collect, Curve Basecrv)
		{
			List<ElementId> list = new List<ElementId>();
			if (Basecrv.IsCyclic)
			{
				XYZ center = (Basecrv as Arc).Center;
				IEnumerator<Element> enumerator = Collect.GetEnumerator();
				{
					while (enumerator.MoveNext())
					{
						Element element = enumerator.Current;
						Wall wall = element as Wall;
						Curve curve = (wall.Location as LocationCurve).Curve;
						if (curve.IsCyclic)
						{
							XYZ center2 = (curve as Arc).Center;
							if (center2.IsAlmostEqualTo(center))
							{
								list.Add(element.Id);
							}
						}
					}
					goto IL_187;
				}
			}
			XYZ xyz = (Basecrv as Line).Direction.Normalize();
			foreach (Element element2 in Collect)
			{
				Wall wall2 = element2 as Wall;
				Curve curve2 = (wall2.Location as LocationCurve).Curve;
				if (curve2 is Line)
				{
					XYZ xyz2 = (curve2 as Line).Direction.Normalize();
					if (xyz2.IsAlmostEqualTo(xyz) || xyz2.IsAlmostEqualTo(xyz.Negate()))
					{
						Curve curve3 = Basecrv.Clone();
						curve3.MakeUnbound();
						XYZ xyzpoint = curve3.Project(curve2.GetEndPoint(0)).XYZPoint;
						XYZ xyzpoint2 = curve3.Project(curve2.GetEndPoint(1)).XYZPoint;
						Curve curve4 = Line.CreateBound(xyzpoint, xyzpoint2);
						SetComparisonResult setComparisonResult = curve4.Intersect(Basecrv);
                        if ((int)setComparisonResult == 64)
						{
							list.Add(element2.Id);
						}
					}
				}
			}
			IL_187:
			this.BreakWallByArchLayer(ref list);
			return list;
		}

		public List<ElementId> GetWallHasComponetIntersectionWithLinkWall()
		{
			List<ElementId> list = new List<ElementId>();
			XYZ xyz = new XYZ(base.ElementData.TransFormedBoundBox.Min.X, base.ElementData.TransFormedBoundBox.Min.Y, base.ElementData.TransFormedBoundBox.Min.Z + 0.01);
			XYZ xyz2 = new XYZ(base.ElementData.TransFormedBoundBox.Max.X, base.ElementData.TransFormedBoundBox.Max.Y, base.ElementData.TransFormedBoundBox.Max.Z - 0.01);
			Outline outline = new Outline(xyz, xyz2);
			BoundingBoxIntersectsFilter boundingBoxIntersectsFilter = new BoundingBoxIntersectsFilter(outline);
			ElementCategoryFilter elementCategoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_Windows);
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc);
			LogicalAndFilter logicalAndFilter = new LogicalAndFilter(elementCategoryFilter, boundingBoxIntersectsFilter);
			filteredElementCollector.WherePasses(logicalAndFilter).WhereElementIsNotElementType();
			foreach (Element element in filteredElementCollector)
			{
				XYZ point = (element.Location as LocationPoint).Point;
				double dWdith = this.m_Doc.GetElement(element.GetTypeId()).get_Parameter(BuiltInParameter.CASEWORK_WIDTH).AsDouble();
				ElementId id = (element as FamilyInstance).Host.Id;
				if (this.CheckIfComponetIntersectWithWall(point, dWdith, id))
				{
					list.Add(id);
				}
			}
			ElementCategoryFilter elementCategoryFilter2 = new ElementCategoryFilter(BuiltInCategory.OST_Doors);
			FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(this.m_Doc);
			LogicalAndFilter logicalAndFilter2 = new LogicalAndFilter(elementCategoryFilter2, boundingBoxIntersectsFilter);
			filteredElementCollector2.WherePasses(logicalAndFilter2).WhereElementIsNotElementType();
			foreach (Element element2 in filteredElementCollector2)
			{
				XYZ point2 = (element2.Location as LocationPoint).Point;
				double num = this.m_Doc.GetElement(element2.GetTypeId()).get_Parameter(BuiltInParameter.CASEWORK_WIDTH).AsDouble();
				Parameter parameter = this.m_Doc.GetElement(element2.GetTypeId()).LookupParameter("导轨深度");
				if (parameter != null)
				{
					num += parameter.AsDouble() * 2.0;
					string familyName = (this.m_Doc.GetElement(element2.GetTypeId()) as FamilySymbol).FamilyName;
					if (familyName.Contains("水雾式钢特级防火卷帘"))
					{
						num += AssistFunc.mmToFeet(400.0);
					}
				}
				ElementId id2 = (element2 as FamilyInstance).Host.Id;
				if (this.CheckIfComponetIntersectWithWall(point2, num, id2))
				{
					list.Add(id2);
				}
			}
			ElementCategoryFilter elementCategoryFilter3 = new ElementCategoryFilter(BuiltInCategory.OST_SpecialityEquipment);
			FilteredElementCollector filteredElementCollector3 = new FilteredElementCollector(this.m_Doc);
			LogicalAndFilter logicalAndFilter3 = new LogicalAndFilter(elementCategoryFilter3, boundingBoxIntersectsFilter);
			filteredElementCollector3.WherePasses(logicalAndFilter3).WhereElementIsNotElementType();
			foreach (Element element3 in filteredElementCollector3)
			{
				List<Guid> list2 = element3.GetEntitySchemaGuids() as List<Guid>;
				if (list2.FindIndex((Guid e) => e.CompareTo(ElevatorXDataManager.m_Guid) == 0) != -1)
				{
					XYZ point3 = (element3.Location as LocationPoint).Point;
					IList<Parameter> parameters = element3.GetParameters("门宽");
					if (parameters.Count<Parameter>() > 0)
					{
						double dWdith2 = parameters[0].AsDouble();
						ElementId id3 = (element3 as FamilyInstance).Host.Id;
						if (this.CheckIfComponetIntersectWithWall(point3, dWdith2, id3))
						{
							list.Add(id3);
						}
					}
				}
			}
			list.Distinct<ElementId>();
			return list;
		}

		private bool CheckIfComponetIntersectWithWall(XYZ insertPt, double dWdith, ElementId wallId)
		{
			Wall wall = this.m_Doc.GetElement(wallId) as Wall;
			Curve curve = (wall.Location as LocationCurve).Curve;
			Curve locatinCrv = (base.ElementData as WallDataPack).LocatinCrv;
			insertPt = new XYZ(insertPt.X, insertPt.Y, locatinCrv.GetEndPoint(0).Z);
			if (curve.IsCyclic || locatinCrv.IsCyclic)
			{
				return false;
			}
			Line line = curve as Line;
			XYZ xyz = line.Direction.Normalize();
			XYZ xyz2 = insertPt - xyz * (dWdith / 2.0);
			XYZ xyz3 = insertPt + xyz * (dWdith / 2.0);
			XYZ endPoint = locatinCrv.GetEndPoint(0);
			XYZ endPoint2 = locatinCrv.GetEndPoint(1);
			Line line2 = Line.CreateUnbound(endPoint, (locatinCrv as Line).Direction.Normalize());
			XYZ xyzpoint = line2.Project(xyz2).XYZPoint;
			XYZ xyzpoint2 = line2.Project(xyz3).XYZPoint;
			double parameter = locatinCrv.Project(xyzpoint).Parameter;
			double parameter2 = locatinCrv.Project(xyzpoint2).Parameter;
			if (!locatinCrv.IsInside(parameter))
			{
				bool flag = locatinCrv.IsInside(parameter2);
				return flag && !xyz3.IsAlmostEqualTo(endPoint) && !xyz3.IsAlmostEqualTo(endPoint2);
			}
			return !xyz2.IsAlmostEqualTo(endPoint) && !xyz2.IsAlmostEqualTo(endPoint2);
		}

		private void BreakWallByArchLayer(ref List<ElementId> lstCurrentId)
		{
			List<Wall> list = new List<Wall>();
			foreach (ElementId elementId in lstCurrentId)
			{
				Wall item = this.m_Doc.GetElement(elementId) as Wall;
				list.Add(item);
			}
			List<Level> list2 = new List<Level>();
			this.InitLevelList(ref list2);
			List<ElementId> list3 = new List<ElementId>();
			WallBreakManager wallBreakManager = new WallBreakManager(this.m_Doc);
			Result result = wallBreakManager.BreakByLevel(list, list2, ref list3, false, null);
			if (result == Autodesk.Revit.UI.Result.Failed)
			{
				return;
			}
			double val = Convert.ToDouble(list2[0].Elevation);
			double val2 = Convert.ToDouble(list2[list2.Count - 1].Elevation);
			this.GetWallElevator(base.ElementData.SelfDoc, base.ElementData.SelfElementId, ref val, ref val2);
			if (list3.Count > 1)
			{
				lstCurrentId.Clear();
				foreach (ElementId elementId2 in list3)
				{
					double val3 = 0.0;
					double val4 = 0.0;
					this.GetWallElevator(this.m_Doc, elementId2, ref val3, ref val4);
					if (Geometry.Greaterthan_Or_Equal(val3, val) && Geometry.Lessthan_Or_Equal(val4, val2))
					{
						lstCurrentId.Add(elementId2);
					}
				}
			}
		}

		private void InitLevelList(ref List<Level> lstLevel)
		{
			FilteredElementIterator elementIterator = new FilteredElementCollector(base.ElementData.SelfDoc).OfClass(typeof(Level)).GetElementIterator();
			elementIterator.Reset();
			SortedList sortedList = new SortedList();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				Level level = element as Level;
				if (level != null)
				{
					sortedList.Add(level.Elevation, level);
				}
			}
			FilteredElementIterator elementIterator2 = new FilteredElementCollector(this.m_Doc).OfClass(typeof(Level)).GetElementIterator();
			elementIterator2.Reset();
			List<Level> list = new List<Level>();
			while (elementIterator2.MoveNext())
			{
				Element element2 = elementIterator2.Current;
				Level level2 = element2 as Level;
				if (level2 != null)
				{
					for (int i = 0; i < sortedList.Count; i++)
					{
						if (Geometry.IsEqual(level2.Elevation, double.Parse(sortedList.GetKey(i).ToString())))
						{
							list.Add(level2);
							break;
						}
					}
				}
			}
			lstLevel = (from e in list
			orderby e.Elevation
			select e).ToList<Level>();
		}

		private void GetWallElevator(Document doc, ElementId elementId, ref double baseLevelValue, ref double topLevelValue)
		{
			Wall wall = doc.GetElement(elementId) as Wall;
			ElementId elementId2 = wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).AsElementId();
			Level level = doc.GetElement(elementId2) as Level;
			double num = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).AsDouble();
			double num2 = wall.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).AsDouble();
			baseLevelValue = level.Elevation + num;
			topLevelValue = baseLevelValue + num2;
		}

		private Curve m_LinkWallCrv;

		private List<ElementId> m_lstWallIdHasIntersectionComponet = new List<ElementId>();
	}
}
